package com.datagateway.controller;

import com.datagateway.component.RateLimiterManager;
import com.datagateway.component.CircuitBreakerManager;
import com.datagateway.component.DegradationManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 流控控制器
 * 提供限流、熔断、降级相关的REST API接口
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@RestController
@RequestMapping("/data-gateway/api/flow-control")
public class FlowControlController {

    @Autowired
    private RateLimiterManager rateLimiterManager;

    @Autowired
    private CircuitBreakerManager circuitBreakerManager;

    @Autowired
    private DegradationManager degradationManager;

    /**
     * 创建限流器
     * 
     * @param request 创建限流器请求
     * @return 操作结果
     */
    @PostMapping("/rate-limiters")
    public Map<String, Object> createRateLimiter(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            String key = (String) request.get("key");
            String algorithm = (String) request.get("algorithm");
            Integer capacity = (Integer) request.get("capacity");
            Integer refillRate = (Integer) request.get("refillRate");
            Integer windowSize = (Integer) request.get("windowSize");
            Integer maxRequests = (Integer) request.get("maxRequests");
            
            if (key == null || algorithm == null || capacity == null || refillRate == null || 
                windowSize == null || maxRequests == null) {
                result.put("success", false);
                result.put("message", "缺少必要参数: key, algorithm, capacity, refillRate, windowSize, maxRequests");
                return result;
            }
            
            boolean success = rateLimiterManager.createRateLimiter(key, algorithm, capacity, 
                refillRate, windowSize, maxRequests);
            
            result.put("success", success);
            result.put("message", success ? "限流器创建成功" : "限流器创建失败");
            result.put("key", key);
            result.put("algorithm", algorithm);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "创建限流器异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 检查限流状态
     * 
     * @param key 限流键
     * @param tokens 令牌数
     * @return 限流结果
     */
    @GetMapping("/rate-limiters/{key}/check")
    public Map<String, Object> checkRateLimit(@PathVariable String key, 
                                            @RequestParam(defaultValue = "1") int tokens) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean allowed = rateLimiterManager.isAllowed(key, tokens);
            
            result.put("success", true);
            result.put("allowed", allowed);
            result.put("key", key);
            result.put("tokens", tokens);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "检查限流状态异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取限流器状态
     * 
     * @param key 限流键
     * @return 限流器状态
     */
    @GetMapping("/rate-limiters/{key}/status")
    public Map<String, Object> getRateLimiterStatus(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            RateLimiterManager.RateLimiterStatus status = rateLimiterManager.getRateLimiterStatus(key);
            
            if (status != null) {
                result.put("success", true);
                result.put("status", status);
            } else {
                result.put("success", false);
                result.put("message", "限流器不存在");
            }
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取限流器状态异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取所有限流器状态
     * 
     * @return 限流器状态列表
     */
    @GetMapping("/rate-limiters/status")
    public Map<String, Object> getAllRateLimiterStatus() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<RateLimiterManager.RateLimiterStatus> statusList = rateLimiterManager.getAllRateLimiterStatus();
            
            result.put("success", true);
            result.put("statusList", statusList);
            result.put("count", statusList.size());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取限流器状态列表异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 删除限流器
     * 
     * @param key 限流键
     * @return 操作结果
     */
    @DeleteMapping("/rate-limiters/{key}")
    public Map<String, Object> removeRateLimiter(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = rateLimiterManager.removeRateLimiter(key);
            
            result.put("success", success);
            result.put("message", success ? "限流器删除成功" : "限流器删除失败");
            result.put("key", key);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "删除限流器异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 创建熔断器
     * 
     * @param request 创建熔断器请求
     * @return 操作结果
     */
    @PostMapping("/circuit-breakers")
    public Map<String, Object> createCircuitBreaker(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            String key = (String) request.get("key");
            Integer failureThreshold = (Integer) request.get("failureThreshold");
            Integer successThreshold = (Integer) request.get("successThreshold");
            Long timeoutMs = ((Number) request.get("timeoutMs")).longValue();
            Long recoveryTimeoutMs = ((Number) request.get("recoveryTimeoutMs")).longValue();
            
            if (key == null || failureThreshold == null || successThreshold == null || 
                timeoutMs == null || recoveryTimeoutMs == null) {
                result.put("success", false);
                result.put("message", "缺少必要参数: key, failureThreshold, successThreshold, timeoutMs, recoveryTimeoutMs");
                return result;
            }
            
            boolean success = circuitBreakerManager.createCircuitBreaker(key, failureThreshold, 
                successThreshold, timeoutMs, recoveryTimeoutMs);
            
            result.put("success", success);
            result.put("message", success ? "熔断器创建成功" : "熔断器创建失败");
            result.put("key", key);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "创建熔断器异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取熔断器状态
     * 
     * @param key 熔断器键
     * @return 熔断器状态
     */
    @GetMapping("/circuit-breakers/{key}/status")
    public Map<String, Object> getCircuitBreakerStatus(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            CircuitBreakerManager.CircuitBreakerStatus status = circuitBreakerManager.getCircuitBreakerStatus(key);
            
            if (status != null) {
                result.put("success", true);
                result.put("status", status);
            } else {
                result.put("success", false);
                result.put("message", "熔断器不存在");
            }
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取熔断器状态异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取所有熔断器状态
     * 
     * @return 熔断器状态列表
     */
    @GetMapping("/circuit-breakers/status")
    public Map<String, Object> getAllCircuitBreakerStatus() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<CircuitBreakerManager.CircuitBreakerStatus> statusList = circuitBreakerManager.getAllCircuitBreakerStatus();
            
            result.put("success", true);
            result.put("statusList", statusList);
            result.put("count", statusList.size());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取熔断器状态列表异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 重置熔断器
     * 
     * @param key 熔断器键
     * @return 操作结果
     */
    @PostMapping("/circuit-breakers/{key}/reset")
    public Map<String, Object> resetCircuitBreaker(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = circuitBreakerManager.resetCircuitBreaker(key);
            
            result.put("success", success);
            result.put("message", success ? "熔断器重置成功" : "熔断器重置失败");
            result.put("key", key);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "重置熔断器异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 删除熔断器
     * 
     * @param key 熔断器键
     * @return 操作结果
     */
    @DeleteMapping("/circuit-breakers/{key}")
    public Map<String, Object> removeCircuitBreaker(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = circuitBreakerManager.removeCircuitBreaker(key);
            
            result.put("success", success);
            result.put("message", success ? "熔断器删除成功" : "熔断器删除失败");
            result.put("key", key);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "删除熔断器异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 创建降级策略
     * 
     * @param request 创建降级策略请求
     * @return 操作结果
     */
    @PostMapping("/degradation-strategies")
    public Map<String, Object> createDegradationStrategy(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            String key = (String) request.get("key");
            String strategyType = (String) request.get("strategyType");
            Double threshold = ((Number) request.get("threshold")).doubleValue();
            Integer duration = (Integer) request.get("duration");
            String fallbackAction = (String) request.get("fallbackAction");
            
            if (key == null || strategyType == null || threshold == null || 
                duration == null || fallbackAction == null) {
                result.put("success", false);
                result.put("message", "缺少必要参数: key, strategyType, threshold, duration, fallbackAction");
                return result;
            }
            
            boolean success = degradationManager.createDegradationStrategy(key, strategyType, 
                threshold, duration, fallbackAction);
            
            result.put("success", success);
            result.put("message", success ? "降级策略创建成功" : "降级策略创建失败");
            result.put("key", key);
            result.put("strategyType", strategyType);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "创建降级策略异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 检查降级状态
     * 
     * @param key 降级键
     * @param currentValue 当前值
     * @return 降级结果
     */
    @GetMapping("/degradation-strategies/{key}/check")
    public Map<String, Object> checkDegradation(@PathVariable String key, 
                                              @RequestParam double currentValue) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean shouldDegrade = degradationManager.shouldDegrade(key, currentValue);
            
            result.put("success", true);
            result.put("shouldDegrade", shouldDegrade);
            result.put("key", key);
            result.put("currentValue", currentValue);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "检查降级状态异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取降级状态
     * 
     * @param key 降级键
     * @return 降级状态
     */
    @GetMapping("/degradation-strategies/{key}/status")
    public Map<String, Object> getDegradationStatus(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            DegradationManager.DegradationStatus status = degradationManager.getDegradationStatus(key);
            
            if (status != null) {
                result.put("success", true);
                result.put("status", status);
            } else {
                result.put("success", false);
                result.put("message", "降级策略不存在");
            }
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取降级状态异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取所有降级状态
     * 
     * @return 降级状态列表
     */
    @GetMapping("/degradation-strategies/status")
    public Map<String, Object> getAllDegradationStatus() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            List<DegradationManager.DegradationStatus> statusList = degradationManager.getAllDegradationStatus();
            
            result.put("success", true);
            result.put("statusList", statusList);
            result.put("count", statusList.size());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取降级状态列表异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 手动触发降级
     * 
     * @param key 降级键
     * @param reason 降级原因
     * @return 操作结果
     */
    @PostMapping("/degradation-strategies/{key}/trigger")
    public Map<String, Object> triggerDegradation(@PathVariable String key, 
                                                 @RequestParam String reason) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = degradationManager.triggerDegradation(key, reason);
            
            result.put("success", success);
            result.put("message", success ? "降级触发成功" : "降级触发失败");
            result.put("key", key);
            result.put("reason", reason);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "触发降级异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 手动恢复降级
     * 
     * @param key 降级键
     * @return 操作结果
     */
    @PostMapping("/degradation-strategies/{key}/recover")
    public Map<String, Object> recoverDegradation(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = degradationManager.recoverDegradation(key);
            
            result.put("success", success);
            result.put("message", success ? "降级恢复成功" : "降级恢复失败");
            result.put("key", key);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "恢复降级异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 删除降级策略
     * 
     * @param key 降级键
     * @return 操作结果
     */
    @DeleteMapping("/degradation-strategies/{key}")
    public Map<String, Object> removeDegradationStrategy(@PathVariable String key) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            boolean success = degradationManager.removeDegradationStrategy(key);
            
            result.put("success", success);
            result.put("message", success ? "降级策略删除成功" : "降级策略删除失败");
            result.put("key", key);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "删除降级策略异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取限流统计信息
     * 
     * @return 统计信息
     */
    @GetMapping("/statistics/rate-limiters")
    public Map<String, Object> getRateLimiterStatistics() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            RateLimiterManager.RateLimiterStatistics stats = rateLimiterManager.getStatistics();
            
            result.put("success", true);
            result.put("statistics", stats);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取限流统计异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取熔断器统计信息
     * 
     * @return 统计信息
     */
    @GetMapping("/statistics/circuit-breakers")
    public Map<String, Object> getCircuitBreakerStatistics() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            CircuitBreakerManager.CircuitBreakerStatistics stats = circuitBreakerManager.getStatistics();
            
            result.put("success", true);
            result.put("statistics", stats);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取熔断器统计异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取降级统计信息
     * 
     * @return 统计信息
     */
    @GetMapping("/statistics/degradation")
    public Map<String, Object> getDegradationStatistics() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            DegradationManager.DegradationStatistics stats = degradationManager.getStatistics();
            
            result.put("success", true);
            result.put("statistics", stats);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取降级统计异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 设置限流配置
     * 
     * @param request 配置请求
     * @return 操作结果
     */
    @PostMapping("/config/rate-limiters")
    public Map<String, Object> setRateLimiterConfiguration(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            Boolean enabled = (Boolean) request.get("enabled");
            String defaultAlgorithm = (String) request.get("defaultAlgorithm");
            Integer defaultCapacity = (Integer) request.get("defaultCapacity");
            Integer defaultRefillRate = (Integer) request.get("defaultRefillRate");
            Integer defaultWindowSize = (Integer) request.get("defaultWindowSize");
            Integer defaultMaxRequests = (Integer) request.get("defaultMaxRequests");
            
            if (enabled == null || defaultAlgorithm == null || defaultCapacity == null || 
                defaultRefillRate == null || defaultWindowSize == null || defaultMaxRequests == null) {
                result.put("success", false);
                result.put("message", "缺少必要参数");
                return result;
            }
            
            rateLimiterManager.setConfiguration(enabled, defaultAlgorithm, defaultCapacity, 
                defaultRefillRate, defaultWindowSize, defaultMaxRequests);
            
            result.put("success", true);
            result.put("message", "限流配置设置成功");
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "设置限流配置异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 设置熔断器配置
     * 
     * @param request 配置请求
     * @return 操作结果
     */
    @PostMapping("/config/circuit-breakers")
    public Map<String, Object> setCircuitBreakerConfiguration(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            Boolean enabled = (Boolean) request.get("enabled");
            Integer defaultFailureThreshold = (Integer) request.get("defaultFailureThreshold");
            Integer defaultSuccessThreshold = (Integer) request.get("defaultSuccessThreshold");
            Long defaultTimeoutMs = ((Number) request.get("defaultTimeoutMs")).longValue();
            Long defaultRecoveryTimeoutMs = ((Number) request.get("defaultRecoveryTimeoutMs")).longValue();
            
            if (enabled == null || defaultFailureThreshold == null || defaultSuccessThreshold == null || 
                defaultTimeoutMs == null || defaultRecoveryTimeoutMs == null) {
                result.put("success", false);
                result.put("message", "缺少必要参数");
                return result;
            }
            
            circuitBreakerManager.setConfiguration(enabled, defaultFailureThreshold, defaultSuccessThreshold, 
                defaultTimeoutMs, defaultRecoveryTimeoutMs);
            
            result.put("success", true);
            result.put("message", "熔断器配置设置成功");
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "设置熔断器配置异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 设置降级配置
     * 
     * @param request 配置请求
     * @return 操作结果
     */
    @PostMapping("/config/degradation")
    public Map<String, Object> setDegradationConfiguration(@RequestBody Map<String, Object> request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            Boolean enabled = (Boolean) request.get("enabled");
            Double cpuThreshold = ((Number) request.get("cpuThreshold")).doubleValue();
            Double memoryThreshold = ((Number) request.get("memoryThreshold")).doubleValue();
            Double responseTimeThreshold = ((Number) request.get("responseTimeThreshold")).doubleValue();
            Double errorRateThreshold = ((Number) request.get("errorRateThreshold")).doubleValue();
            Integer degradationDuration = (Integer) request.get("degradationDuration");
            
            if (enabled == null || cpuThreshold == null || memoryThreshold == null || 
                responseTimeThreshold == null || errorRateThreshold == null || degradationDuration == null) {
                result.put("success", false);
                result.put("message", "缺少必要参数");
                return result;
            }
            
            degradationManager.setConfiguration(enabled, cpuThreshold, memoryThreshold, 
                responseTimeThreshold, errorRateThreshold, degradationDuration);
            
            result.put("success", true);
            result.put("message", "降级配置设置成功");
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "设置降级配置异常: " + e.getMessage());
        }
        
        return result;
    }

    /**
     * 获取流控概览
     * 
     * @return 概览信息
     */
    @GetMapping("/overview")
    public Map<String, Object> getFlowControlOverview() {
        Map<String, Object> result = new HashMap<>();
        
        try {
            RateLimiterManager.RateLimiterStatistics rateLimiterStats = rateLimiterManager.getStatistics();
            CircuitBreakerManager.CircuitBreakerStatistics circuitBreakerStats = circuitBreakerManager.getStatistics();
            DegradationManager.DegradationStatistics degradationStats = degradationManager.getStatistics();
            
            Map<String, Object> overview = new HashMap<>();
            overview.put("rateLimiterStatistics", rateLimiterStats);
            overview.put("circuitBreakerStatistics", circuitBreakerStats);
            overview.put("degradationStatistics", degradationStats);
            overview.put("timestamp", System.currentTimeMillis());
            
            result.put("success", true);
            result.put("overview", overview);
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "获取流控概览异常: " + e.getMessage());
        }
        
        return result;
    }
}
